package com.lambda;

import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

public class 函数式接口引用式写法 {
	public static void main(String[] args) {
		MyInterface my = System.out::println;
		my.saySomething("abc");
		
		
		/**
		 * Function<T, R>
		 * 接收一个T类型的参数并返回R类型的返回值
		 * apply(param)将参数应用于函数执行
		 * andThen(Function<T,R> after)返回一个组合函数，将前面函数得到的结果做为参数传给after
		 * compose(Function<T,R> before)返回一个组合函数，先执行before得到结果后做为参数传给调用者
		 */
		Function<Integer, Integer> fun1 = param -> param + 2;
		Function<Integer, Integer> fun2 = param -> param*2;
		System.out.println(fun1.apply(2));
		//先执行fun1().apply(3)得到结果R，然后将R应用到fun2
		System.out.println(fun1.andThen(fun2).apply(3));
		//先执行fun2.apply(3)得到结果R，然后将R应用到fun1
		System.out.println(fun1.compose(fun2).apply(3));
		System.out.println(Function.identity().compose(fun2).apply(3));
		
		
		/**
		 * BiFunction<T,U,R>
		 * 接收两个参数，一个参数类型为T，第二个参数类型为U，并返回R类型的返回值
		 */
		BiFunction<Integer,Integer,String> fun3 = (param1,param2) -> "参数1：" + param1 + ",参数2：" + param2;
		Function<String, String> fun4 = param -> "组合参数为：" + param;
		System.out.println(fun3.andThen(fun4).apply(1, 2));
		
		
		
		/**
		 * Consumer<T>
		 * 接收一个T类型参数并且没有返回值
		 * accept(T)将参数应用于函数并执行
		 */
		StringBuilder str = new StringBuilder("init");
		Consumer<StringBuilder> con1 = t -> t.append("-con1");
		con1.accept(str);
		System.out.println(str);
		
		/**
		 * BiConsumer<T,U>
		 * 接收两个参数，第一个参数类型为T，第二个参数类型为U，执行但是不返回结果
		 */
		BiConsumer<String, Integer> con2 = (param1,param2) -> System.out.println("参数1：" + param1 + ",参数2：" + param2);
		con2.accept("param1",2);
		
		
		
		/**
		 * Predicate<T>
		 * 接收一个类型为T类型的参数并返回布尔值
		 * and(Predicate<T> anther) 以短路与的方式加入到前面的运算中，前后两个函数的参数类型必须一致，两个函数的入参都是同一个
		 * or(Predicate<T> anther) 以短路或的方式加入到前面的运算中，前后两个函数的参数类型必须一致，两个函数的入参都是同一个
		 * negate()将结果取反
		 */
		Predicate<Integer> pre1 = t -> t != null;
		Predicate<Integer> pre2 = t -> t > 100;
		System.out.println(pre1.test(100));
		System.out.println(pre1.and(pre2).test(100));
		System.out.println(pre1.or(pre2).test(10));
		System.out.println(pre1.negate().test(null));
		
		
		/**
		 * BiPredicate<T,R>
		 * 给定两个参数并返回布尔值
		 */
		BiPredicate<String, String> pre3 = (param1,param2) -> param1.compareTo(param2) > 0;
		System.out.println(pre3.test("abc", "acb"));
		
		
		/**
		 * 供应商： Supplier<T>
		 * 不提供入参，返回T类型的函数
		 */
		Supplier<String> sup1 = () -> "sup1";
		System.out.println(sup1.get());
		
		/**
		 * BooleanSupplier:没有入参，返回布尔类型
		 */
		BooleanSupplier sup2 = () -> System.currentTimeMillis() > 1000;
		System.out.println(sup2.getAsBoolean());
		
		
		/**
		 * UnaryOperator<T>
		 * 提供一个类型为T的参数并返回类型为T的值
		 */
		UnaryOperator<String> ope1 = t -> "param:" + t;
		System.out.println(ope1.apply("参数"));
		
		
		/**
		 * BinaryOperator<T>
		 * 接收两个类型为T的参数并返回类型为T的值
		 */
		BinaryOperator<String> ope2 = (param1,param2) -> param1 + "-" + param2;
		System.out.println(ope2.apply("param1", "param2"));
		
	}
	
}
interface MyInterface{
	public void saySomething(String someThing);
}
